package ar.pegasus.clasificador.dao.api;

import java.util.ArrayList;
import java.util.List;

import ar.pegasus.clasificador.dao.api.local.CalleDAOLocal;
import ar.pegasus.clasificador.entidades.Seccion;
import ar.pegasus.clasificador.entidades.TramoCalle;
import ar.pegasus.clasificador.entidades.wrappers.CalleWrapper;
import ar.pegasus.clasificador.entidades.wrappers.InterseccionWrapper;
import ar.pegasus.clasificador.entidades.wrappers.TramoCalleWrapper;
import ar.pegasus.clasificador.util.BeanFactoryClasificadorLocal;
import ar.pegasus.clasificador.util.NombreScanner;
import ar.pegasus.clasificador.util.NombreToken;
import ar.pegasus.framework.componentes.PException;

public class CalleManager {

	private static CalleManager instance;

	public static CalleManager getInstance() throws PException {
		if(instance == null){
			instance = new CalleManager();
		}
		return instance;
	}
	
	private CalleDAOLocal calleDAO;
	
	CalleManager() throws PException{
		calleDAO = BeanFactoryClasificadorLocal.getInstance().getBean(CalleDAOLocal.class);
	}

	/**
	 * Determina que el nombre de la calle recibida como String exista dentro de la seccion.
	 * requiere: un lista de string
	 * 
	 * @param calle
	 * @param cod_calle
	 * @param seccion
	 * @return
	 */
	public boolean existeCalle(String calle, long cod_calle, Seccion seccion) {

		String andcond,andend;
		int cant_token;

		NombreScanner scanner = new NombreScanner(calle);
		// Empiezo a Buscar los token y armar la condicion del where
//		token = scanning(tokenlist,tipo )
		NombreToken token = scanner.getToken();
		
		// este es el primer token inicia la condicion debe ser el primero del nombre o del sinonimo
		if (token.getTipo() == NombreScanner.FINALIZADO)
			return false;
		cant_token = 1;

		// armo la condicion de where
		andcond =" (((nombre LIKE '"+ token.getToken() +"%') OR (nombre LIKE '% "+token.getToken() +"%'))";
		andend =" OR (nombre = '" + token.getToken() + "'))";

		// leemos el segundo token
		NombreToken last_token = token;

//		token = scanning( tokenlist, tipo )
		token = scanner.getToken();
		while(token.getTipo() != NombreScanner.FINALIZADO){
			cant_token ++;
			// leemos el tercer y subsiguientes tokens
			last_token = token;
//			token = scanning( tokenlist,tipo )
			token = scanner.getToken();
			
			if (token.getTipo() != NombreScanner.FINALIZADO){
				if( last_token.getToken().length() > 1 ) 
					andcond = andcond + " AND (nombre like '% "+ last_token.getToken() + " %')";
				else{
					// si la longitud es 1 es que es una abreviatura de nombre y entonces
					// busco que empiece con ese token
					andcond = andcond + " AND (nombre like '% " + last_token.getToken() +"%')";
				}
			}
		}
		// se acabaron los tokens por ello debo concatenar el token ya que todavia no se habia concatenado
		andcond = andcond + " AND (nombre like '% " + last_token.getToken() + "')";
		if(cant_token > 1){
			andcond = " AND "+andcond+") ";
			andend = "";
		}else
			andcond = " AND ("+andcond+")";

		// OpenCursor crea e instancia el cursor, lo vuelve a cerrar y retorna true
		// si tenia al menos una fila
		
		return calleDAO.chequearCalle(seccion,andcond, andend);
	}

	/**
	 * Determina que el nombre de la calle recibida como String exista dentro de la seccion.
	 * requiere: un lista de string
	 * 
	 * @param calle
	 * @param cod_calle
	 * @param seccion
	 * @return
	 */
	public List<CalleWrapper> getCalle(String calle, long cod_calle, Seccion seccion) {

		String andcond,andend;
		int cant_token;

		NombreScanner scanner = new NombreScanner(calle);
		// Empiezo a Buscar los token y armar la condicion del where
//		token = scanning(tokenlist,tipo )
		NombreToken token = scanner.getToken();
		
		// este es el primer token inicia la condicion debe ser el primero del nombre o del sinonimo
		if (token.getTipo() == NombreScanner.FINALIZADO)
			return new ArrayList<CalleWrapper>();
		cant_token = 1;

		// armo la condicion de where
		andcond =" (((nombre LIKE '"+ token.getToken() +"%') OR (nombre LIKE '% "+token.getToken() +"%'))";
		andend =" OR (nombre = '" + token.getToken() + "'))";

		// leemos el segundo token
		NombreToken last_token = token;

//		token = scanning( tokenlist, tipo )
		token = scanner.getToken();
		while(token.getTipo() != NombreScanner.FINALIZADO){
			cant_token ++;
			// leemos el tercer y subsiguientes tokens
			last_token = token;
//			token = scanning( tokenlist,tipo )
			token = scanner.getToken();
			
			if (token.getTipo() != NombreScanner.FINALIZADO){
				if( last_token.getToken().length() > 1 ) 
					andcond = andcond + " AND (nombre like '% "+ last_token.getToken() + " %')";
				else{
					// si la longitud es 1 es que es una abreviatura de nombre y entonces
					// busco que empiece con ese token
					andcond = andcond + " AND (nombre like '% " + last_token.getToken() +"%')";
				}
			}
		}
		// se acabaron los tokens por ello debo concatenar el token ya que todavia no se habia concatenado
		andcond = andcond + " AND (nombre like '% " + last_token.getToken() + "')";
		if(cant_token > 1){
			andcond = " AND "+andcond+") ";
			andend = "";
		}else
			andcond = " AND ("+andcond+")";

		// OpenCursor crea e instancia el cursor, lo vuelve a cerrar y retorna true
		// si tenia al menos una fila
		
//		return calleDAO.chequearCalle(seccion,andcond, andend);
		return calleDAO.getCalles(seccion, andcond, andend);
	}

	/**
	 * Retorna la lista de Tramos para la calle con Altura dentro de la localidad
	 * 
	 * @param seccion
	 * @param idCalleBuscada
	 * @param alturaCalle
	 * @param paridad
	 * @return
	 */
	public List<TramoCalleWrapper> getTramosCalleConLocalidadAltura(Seccion seccion, long idCalleBuscada, long alturaCalle, String paridad) {
		return calleDAO.getTramosCalleConLocalidadAltura(seccion.getIdSeccion(), idCalleBuscada, alturaCalle, paridad);
	}

	public List<TramoCalle> getTramosCalleByIdCalle(Seccion seccion, int idCalle) {
		return calleDAO.getTramosCalleByIdCalle(seccion, idCalle);
	}

	public List<TramoCalleWrapper> getTramosCalle(Seccion seccion,	int idCalle) {
		return calleDAO.getTramosCalle(seccion.getIdSeccion(),idCalle);
	}

	public List<InterseccionWrapper> getInterseccionesPorLocalidad(Seccion seccion,int idCallePrincipal, int idCalleSecundaria) {
		return calleDAO.getInterseccionesPorLocalidad(seccion.getIdSeccion(),idCallePrincipal,idCalleSecundaria);
	}

	public List<InterseccionWrapper> getEntreCallesPorLocalidad(Seccion seccion, int idCallePrincipal, int idCalleSecundaria, int idCalleTerciaria) {
		return calleDAO.getEntreCallesPorLocalidad(seccion.getIdSeccion(), idCallePrincipal, idCalleSecundaria, idCalleTerciaria);
	}
	
	public List<InterseccionWrapper> getEntreCalles(Seccion seccion, int idCallePrincipal, int idCalleSecundaria, int idCalleTerciaria) {
		return calleDAO.getEntreCalles(seccion.getIdSeccion(), idCallePrincipal, idCalleSecundaria, idCalleTerciaria);
	}

	public List<TramoCalleWrapper> getTramosCalleConAltura(Seccion seccion, int idCalleBuscada, long alturaCalle, String paridad) {
		return calleDAO.getTramosCalleConAltura(seccion.getIdSeccion(), idCalleBuscada, alturaCalle, paridad);
	}

	public List<InterseccionWrapper> getIntersecciones(Seccion seccion,	int idCallePrincipal, int idCalleSecundaria) {
		return calleDAO.getIntersecciones(seccion.getIdSeccion(),idCallePrincipal,idCalleSecundaria);
	}

}
